<?php

if (!defined('SMF'))
	die('Hacking attempt...');

function snet_process_post($type,$profile)
{
	global $context, $txt, $user_info, $user_profile, $settings, $modSettings, $smcFunc, $sourcedir, $post_data;
	
	require_once($sourcedir . '/Subs-Editor.php');
	require_once($sourcedir . '/Subs-Post.php');
	
	$context['snet_errors'] = array();
	
	// See what type of post this is, for starters.
	switch($type)
	{
		case 1:
			snet_process_text();
			break;
		case 2:
			snet_process_photo();
			break;
		case 3:
			snet_process_link();
			break;		
		case 4:
			snet_process_quote();
			break;	
		case 5:
			snet_process_video();
			break;				
	}
}

function snet_process_text()
{
	global $context, $txt, $user_info, $user_profile, $settings, $modSettings, $smcFunc, $sourcedir, $post_data;

	// Check, check, check, all hands on deck.
	if (!isset($_POST['snet_message']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['snet_message']), ENT_QUOTES) === '')
	{
		$context['snet_errors'][] = 'empty_status';
		$_POST['snet_message'] = '';
	}
	else
	{
		// And the classic egg. I don't like eggs, though, I'm allergic.
		if (isset($_POST['snet_message']) && strtolower($_POST['snet_message']) == 'i am the cookie monster')
		{
			$context['snet_errors'][] = 'the_oven';
			$txt['snet_error_the_oven'] = 'Oh you sure aren\'t, I\'m sitting right here.';
		}
			
		// I SAID ALL HANDS ON CHECK. I mean deck. The check-deck. The decky check. Checkin' deckin'.
		$_POST['snet_message'] = $smcFunc['htmlspecialchars']($_POST['snet_message'], ENT_QUOTES);
		preparsecode($_POST['snet_message']);

		// What's hidin' in there?
		if ($smcFunc['htmltrim'](strip_tags(snet_format_text($_POST['snet_message'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['snet_message'], '[html]') === false))
			$context['snet_errors'][] = 'empty_status';
		elseif (!empty($modSettings['snet_max_status_length']) && $smcFunc['strlen']($_POST['snet_message']) > $modSettings['snet_max_status_length'])
		{
			$context['snet_errors'][] = 'long_status';
			$txt['snet_error_long_status'] = sprintf($txt['snet_error_long_status'], $modSettings['snet_max_status_length']);
		}
	}
	
	if(empty($context['snet_errors']))
	{
		$post_data['type'] = 1;
		$post_data['body'] = $_POST['snet_message'];
	}
}

function snet_process_photo()
{
	global $context, $txt, $user_info, $user_profile, $settings, $modSettings, $smcFunc, $sourcedir, $post_data, $boarddir;
	
	switch($_POST['photo_method'])
	{
		// A webcam photo. This is fun.
		case 1:
			if(empty($_POST['webcam_data_string']))
				$context['snet_errors'][] = 'no_photo';
				
			$image_data = $_POST['webcam_data_string'];

			// Get rid of stuff we don't need.
			$image = substr($image_data,strpos($image_data,',')+1);
			break;
		// An upload
		case 2:
			if(empty($_FILES['snet_image_file']))
				$context['snet_errors'][] = 'no_file';

			$image = $_FILES['snet_image_file'];
			break;
		// An URL upload
		case 3:
			if(empty($_POST['snet_image_link']))
				$context['snet_errors'][] = 'no_link';
				
			$image = $_POST['snet_image_link'];
			break;
	}
			
	// If they entered a caption, make sure its valid
	if(!empty($_POST['snet_caption']))
	{
		$_POST['snet_caption'] = $smcFunc['htmlspecialchars']($_POST['snet_caption'], ENT_QUOTES);
		preparsecode($_POST['snet_caption']);

		if ($smcFunc['htmltrim'](strip_tags(snet_format_text($_POST['snet_caption'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['snet_caption'], '[html]') === false))
			$_POST['snet_caption'] = '';
		elseif (!empty($modSettings['snet_max_status_length']) && $smcFunc['strlen']($_POST['snet_caption']) > $modSettings['snet_max_status_length'])
		{
			$context['snet_errors'][] = 'long_caption';
			$txt['snet_error_long_caption'] = sprintf($txt['snet_error_long_caption'], $modSettings['snet_max_status_length']);
		}	
	}
	
	// Tr to upload it, now.
	if(empty($context['snet_errors']))
		$attachment = snet_upload_image($image,$_POST['photo_method']);
	
	if(empty($context['snet_errors']))
	{
		$post_data['type'] = 2;
		$post_data['body'] = @serialize(array('caption' => !empty($_POST['snet_caption']) ? $_POST['snet_caption'] : '', 'method' => $_POST['photo_method']));
		$post_data['attachment'] = $attachment;
	}
}

function snet_process_link()
{
	global $context, $txt, $user_info, $user_profile, $settings, $modSettings, $smcFunc, $sourcedir, $post_data;

	// Make sure they actually gave us a URL.
	if (!isset($_POST['snet_link']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['snet_link']), ENT_QUOTES) === '')
	{
		$context['snet_errors'][] = 'empty_link';
		$_POST['snet_link'] = '';
	}
	else
	{
		// Make sure it's valid.
		if(!snet_validate_url($_POST['snet_link']))
			$context['snet_errors'][] = 'invalid_link';
		else
		{
			$meta_tags = get_meta_tags($_POST['snet_link']);
			// If they entered a custom title, make sure its valid
			if(!empty($_POST['snet_link_title']))
			{
				if($smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['snet_link_title'])) === '')
					$_POST['snet_link_title'] = '';
				elseif ($smcFunc['strlen']($_POST['snet_link_title']) > 75)
				{
					$too_long = true;
					$context['snet_errors'][] = 'long_title';
					$txt['snet_error_long_title'] = sprintf($txt['snet_error_long_title'], 75);
				}
				$link_title = $_POST['snet_link_title'];
			}
			// If none is provided, grab the link's own title,
			if(empty($link_title) && !$too_long)
			{
				$link_title = $meta_tags['title'];
				if(empty($meta_tags['title']))
				{
					if(!($data = file_get_contents($_POST['snet_link'])))
						$context['snet_errors'][] = 'broken_link';
					if(preg_match("#<title>(.+)<\/title>#iU", $data, $t))
						$link_title = trim($t[1]);
					else
						$link_title = $_POST['snet_link'];
				}
			}
			
			// If they entered a comment, make sure its valid
			if(!empty($_POST['snet_link_comment']))
			{
				$_POST['snet_link_comment'] = $smcFunc['htmlspecialchars']($_POST['snet_link_comment'], ENT_QUOTES);
				preparsecode($_POST['snet_link_comment']);

				if ($smcFunc['htmltrim'](strip_tags(snet_format_text($_POST['snet_link_comment'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['snet_link_comment'], '[html]') === false))
					$_POST['snet_link_comment'] = '';
				elseif (!empty($modSettings['snet_max_status_length']) && $smcFunc['strlen']($_POST['snet_link_comment']) > $modSettings['snet_max_status_length'])
				{
					$context['snet_errors'][] = 'long_comment';
					$txt['snet_error_long_comment'] = sprintf($txt['snet_error_long_comment'], $modSettings['snet_max_status_length']);
				}	
			}
			
			// Finally, get the meta description of this link.
			$link_description = !empty($meta_tags['description']) ? $meta_tags['description'] : '';
		}
	}
	
	if(empty($context['snet_errors']))
	{
		$post_data['type'] = 3;
		$post_data['body'] = @serialize(array('url' => $_POST['snet_link'], 'title' => $link_title, 'description' => $link_description, 'status' => !empty($_POST['snet_link_comment']) ? $_POST['snet_link_comment'] : ''));
	}
}

function snet_process_video()
{
	global $context, $txt, $user_info, $user_profile, $settings, $modSettings, $smcFunc, $sourcedir, $post_data;
	
	// Make sure they actually gave us a URL.
	if (!isset($_POST['snet_video_link']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['snet_video_link']), ENT_QUOTES) === '')
	{
		$context['snet_errors'][] = 'empty_link';
		$_POST['snet_video_link'] = '';
	}
	else
	{
		// Make sure it's valid.
		if(!snet_validate_url($_POST['snet_video_link']))
			$context['snet_errors'][] = 'invalid_link';
		else
		{
			// If they entered a comment, make sure its valid
			if(!empty($_POST['snet_video_comment']))
			{
				$_POST['snet_video_comment'] = $smcFunc['htmlspecialchars']($_POST['snet_video_comment'], ENT_QUOTES);
				preparsecode($_POST['snet_video_comment']);

				if ($smcFunc['htmltrim'](strip_tags(snet_format_text($_POST['snet_comment'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['snet_video_comment'], '[html]') === false))
					$_POST['snet_video_comment'] = '';
				elseif (!empty($modSettings['snet_max_status_length']) && $smcFunc['strlen']($_POST['snet_video_comment']) > $modSettings['snet_max_status_length'])
				{
					$context['snet_errors'][] = 'long_comment';
					$txt['snet_error_long_comment'] = sprintf($txt['snet_error_long_comment'], $modSettings['snet_max_status_length']);
				}	
			}
		}
	}
	
	if(empty($context['snet_errors']))
	{
		$post_data['type'] = 5;
		$post_data['body'] = @serialize(array('url' => $_POST['snet_video_link'], 'status' => !empty($_POST['snet_video_comment']) ? $_POST['snet_video_comment'] : ''));
	}
}

function snet_process_quote()
{
	global $context, $txt, $user_info, $user_profile, $settings, $modSettings, $smcFunc, $sourcedir, $post_data;

	// Empty?!
	if (!isset($_POST['snet_quote']) || $smcFunc['htmltrim']($smcFunc['htmlspecialchars']($_POST['snet_quote']), ENT_QUOTES) === '')
	{
		$context['snet_errors'][] = 'empty_quote';
		$_POST['snet_quote'] = '';
	}
	else
	{
		$_POST['snet_quote'] = $smcFunc['htmlspecialchars']($_POST['snet_quote'], ENT_QUOTES);
		preparsecode($_POST['snet_quote']);
		if ($smcFunc['htmltrim'](strip_tags(snet_format_text($_POST['snet_quote'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['snet_quote'], '[html]') === false))
			$context['snet_errors'][] = 'empty_quote';
		elseif (!empty($modSettings['snet_max_status_length']) && $smcFunc['strlen']($_POST['snet_quote']) > $modSettings['snet_max_status_length'])
		{
			$context['snet_errors'][] = 'long_quote';
			$txt['snet_error_long_quote'] = sprintf($txt['snet_error_long_quote'], $modSettings['snet_max_status_length']);
		}				
			
		// If they entered a source, make sure its valid
		if(!empty($_POST['snet_quote_source']))
		{
			$_POST['snet_quote_source'] = $smcFunc['htmlspecialchars']($_POST['snet_quote_source'], ENT_QUOTES);
			preparsecode($_POST['snet_quote_source']);
			if ($smcFunc['htmltrim'](strip_tags(snet_format_text($_POST['snet_quote_source'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['snet_quote_source'], '[html]') === false))
				$_POST['snet_quote_source'] = '';
			elseif (!empty($modSettings['snet_max_status_length']) && $smcFunc['strlen']($_POST['snet_quote_source']) > $modSettings['snet_max_status_length'])
			{
				$context['snet_errors'][] = 'long_source';
				$txt['snet_error_long_source'] = sprintf($txt['snet_error_long_source'], $modSettings['snet_max_status_length']);
			}	
		}			
			
		// If they entered a comment, make sure its valid
		if(!empty($_POST['snet_quote_comment']))
		{
			$_POST['snet_quote_comment'] = $smcFunc['htmlspecialchars']($_POST['snet_quote_comment'], ENT_QUOTES);
			preparsecode($_POST['snet_quote_comment']);

			if ($smcFunc['htmltrim'](strip_tags(snet_format_text($_POST['snet_quote_comment'], false), '<img>')) === '' && (!allowedTo('admin_forum') || strpos($_POST['snet_quote_comment'], '[html]') === false))
				$_POST['snet_quote_comment'] = '';
			elseif (!empty($modSettings['snet_max_status_length']) && $smcFunc['strlen']($_POST['snet_quote_comment']) > $modSettings['snet_max_status_length'])
			{
				$context['snet_errors'][] = 'long_comment';
				$txt['snet_error_long_comment'] = sprintf($txt['snet_error_long_comment'], $modSettings['snet_max_status_length']);
			}	
		}			
	}
	
	if(empty($context['snet_errors']))
	{
		$post_data['type'] = 4;
		$post_data['body'] = @serialize(array('quote' => $_POST['snet_quote'], 'source' => !empty($_POST['snet_quote_source']) ? $_POST['snet_quote_source'] : '', 'status' => !empty($_POST['snet_quote_comment']) ? $_POST['snet_quote_comment'] : ''));
	}
}

function snet_post_status_update($post_data,$profile,$user = false,$return = false)
{
	global $context, $txt, $user_info, $user_profile, $settings, $modSettings, $smcFunc, $sourcedir;
	
	if(!$user)
		$user = $user_info['id'];
		
	// Just put it into the database already...
	$smcFunc['db_insert']('',
		'{db_prefix}snet_status_updates',
		array(
			'id_profile' => 'int', 'id_user' => 'int', 'type' => 'int', 'date' => 'int', 'body' => 'string',
		),
		array(
			$profile, $user, $post_data['type'], mktime(), utf8_encode($post_data['body']),
		),			
		array('id_status')
	);	
	$id_status = $smcFunc['db_insert_id']('{db_prefix}snet_status_updates', 'id_status');
	
	if(isset($post_data['attachment']))
	{
		// Finally, add this to SN's own attachments table.
		$smcFunc['db_insert']('',
			'{db_prefix}snet_attachments',
			array(
				'id_attach' => 'int', 'id_status' => 'int', 'id_thumb' => 'int',
			),
			array(
				$post_data['attachment']['id'], $id_status, !empty($post_data['attachment']['thumb']) ? $post_data['attachment']['thumb'] : 0,
			),
			array('id_attach')
		);
	}
	
	if($return)
		return $id_status;
}

function snet_file_extension($file = '')
{
	if(empty($file))
		return false;

	$file = strtolower($file); 
	$extensionarray = explode('.',$file); 
	return end($extensionarray); 
}

function snet_upload_image($image,$type)
{
	global $context, $txt, $user_info, $user_profile, $settings, $modSettings, $smcFunc, $sourcedir;
	
	$attachID = 'snet_image_' . $user_info['id'] . '_' . $context['member']['id']. '.tmp';
	
	// Make sure we're uploading to the right place.
	if (!empty($modSettings['currentAttachmentUploadDir']))
	{
		if (!is_array($modSettings['attachmentUploadDir']))
			$modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']);

		// The current directory, of course!
		$current_attach_dir = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
	}
	else
		$current_attach_dir = $modSettings['attachmentUploadDir'];	

	switch($type)
	{
		// Webcam; download it from a URL.
		case 1:
				// Go ahead and save a temp file to the server.
				$image_destination = $current_attach_dir . '/' . $attachID;
				$image_file = fopen($image_destination,'w');
				fwrite($image_file, base64_decode($image));
				fclose($image_file);
				$extension = 'jpg';
			break;
			
		// Image upload.
		case 2:
				$image_destination = $current_attach_dir . '/' . $attachID;
				$image_file = $_FILES['snet_image_file']['tmp_name'];
				$image_name = $_FILES['snet_image_file']['name'];
				if(!move_uploaded_file($_FILES['snet_image_file']['tmp_name'],$image_destination))
					fatal_lang_error('attach_timeout', 'critical');	
			break;
		// Image upload via URL.
		case 3:
			// Go ahead and save a temp file to the server.
			$image_destination = $current_attach_dir . '/' . $attachID;
			$image_file = fopen($image_destination,'w');
			fwrite($image_file, file_get_contents($image));
			fclose($image_file);
			$extension = snet_file_extension($image);
			break;	
		// A link thumnbail
		case 4:
			$document = new DOMDocument();
			$document->loadHTML(file_get_contents($image));
			$xml = simplexml_import_dom($document);
			$images = $xml->xpath('//img');
			$image_destination = $current_attach_dir . '/' . $attachID;
			$image_file = fopen($image_destination,'w');
			fwrite($image_file, file_get_contents($images[0]['src']));
			fclose($image_file);
			$extension = snet_file_extension($images[0]['src']);
			break;
	}

		@chmod($image_destination, 0644);

		// Check the total upload size for this post...
		if (!empty($modSettings['attachmentPostLimit']) && $image_file['size'] > $modSettings['attachmentPostLimit'] * 1024)
		{
			checkSubmitOnce('free');
			fatal_lang_error('file_too_big', false, array($modSettings['attachmentPostLimit']));
		}

		$attachmentOptions = array(
			'post' => 0,
			'poster' => $user_info['id'],
			'name' => !empty($image_name) ? $image_name : 'snet_image_' . mktime() . mt_rand(0,1337) . '.' .$extension,
			'tmp_name' => $image_destination,
			'size' => filesize($image_destination),
			'approved' => 1,
			'fileext' => !empty($extension) ? $extension : '',
			'imagetype' => $type,
		);

		if (!snet_create_attachment($attachmentOptions))
		{
			if (in_array('could_not_upload', $attachmentOptions['errors']))
			{
				checkSubmitOnce('free');
				fatal_lang_error('attach_timeout', 'critical');
			}
			if (in_array('too_large', $attachmentOptions['errors']))
			{
				checkSubmitOnce('free');
				fatal_lang_error('file_too_big', false, array($modSettings['attachmentSizeLimit']));
			}
			if (in_array('bad_extension', $attachmentOptions['errors']))
			{
				checkSubmitOnce('free');
				fatal_error($attachmentOptions['name'] . '.<br />' . $txt['cant_upload_type'] . ' ' . $modSettings['attachmentExtensions'] . '.', false);
			}
			if (in_array('directory_full', $attachmentOptions['errors']))
			{
				checkSubmitOnce('free');
				fatal_lang_error('ran_out_of_space', 'critical');
			}
			if (in_array('bad_filename', $attachmentOptions['errors']))
			{
				checkSubmitOnce('free');
				fatal_error(basename($attachmentOptions['name']) . '.<br />' . $txt['restricted_filename'] . '.', 'critical');
			}
			if (in_array('taken_filename', $attachmentOptions['errors']))
			{
				checkSubmitOnce('free');
				fatal_lang_error('filename_exists');
			}
			if (in_array('bad_attachment', $attachmentOptions['errors']))
			{
				checkSubmitOnce('free');
				fatal_lang_error('bad_attachment');
			}
		}
		
		$attachment_array = array(
			'id' => $attachmentOptions['id'],
			'thumb' => !empty($attachmentOptions['thumb']) ? $attachmentOptions['thumb'] : 0,
		);
		return $type == 4 && isset($attachmentOptions['thumb']) ? $attachmentOptions['thumb'] : $attachment_array;
	
}

// Edited version of createAttachment, from Subs-Post.php, SMF 2.0 RC4. Copyright 2006-2010 by Simple Machines LLC
function snet_create_attachment(&$attachmentOptions)
{
	global $modSettings, $sourcedir, $smcFunc, $context;

	require_once($sourcedir . '/Subs-Graphics.php');

	// We need to know where this thing is going.
	if (!empty($modSettings['currentAttachmentUploadDir']))
	{
		if (!is_array($modSettings['attachmentUploadDir']))
			$modSettings['attachmentUploadDir'] = unserialize($modSettings['attachmentUploadDir']);

		// Just use the current path for temp files.
		$attach_dir = $modSettings['attachmentUploadDir'][$modSettings['currentAttachmentUploadDir']];
		$id_folder = $modSettings['currentAttachmentUploadDir'];
	}
	else
	{
		$attach_dir = $modSettings['attachmentUploadDir'];
		$id_folder = 1;
	}

	$attachmentOptions['errors'] = array();

	// These are the only valid image types for SMF.
	$validImageTypes = array(
		1 => 'gif',
		2 => 'jpeg',
		3 => 'png',
		5 => 'psd',
		6 => 'bmp',
		7 => 'tiff',
		8 => 'tiff',
		9 => 'jpeg',
		14 => 'iff'
	);

	// Get the hash if no hash has been given yet.
	if (empty($attachmentOptions['file_hash']))
		$attachmentOptions['file_hash'] = getAttachmentFilename($attachmentOptions['name'], false, null, true);

	// Is the file too big?
	if (!empty($modSettings['attachmentSizeLimit']) && $attachmentOptions['size'] > $modSettings['attachmentSizeLimit'] * 1024)
		$attachmentOptions['errors'][] = 'too_large';

	if (!empty($modSettings['attachmentCheckExtensions']))
	{
		$allowed = explode(',', strtolower($modSettings['attachmentExtensions']));
		foreach ($allowed as $k => $dummy)
			$allowed[$k] = trim($dummy);

		if (!in_array(strtolower(substr(strrchr($attachmentOptions['name'], '.'), 1)), $allowed))
			$attachmentOptions['errors'][] = 'bad_extension';
	}

	if (!empty($modSettings['attachmentDirSizeLimit']))
	{
		// Make sure the directory isn't full.
		$dirSize = 0;
		$dir = @opendir($attach_dir) or fatal_lang_error('cant_access_upload_path', 'critical');
		while ($file = readdir($dir))
		{
			if ($file == '.' || $file == '..')
				continue;

			if (preg_match('~^post_tmp_\d+_\d+$~', $file) != 0)
			{
				// Temp file is more than 5 hours old!
				if (filemtime($attach_dir . '/' . $file) < time() - 18000)
					@unlink($attach_dir . '/' . $file);
				continue;
			}

			$dirSize += filesize($attach_dir . '/' . $file);
		}
		closedir($dir);

		// Too big!  Maybe you could zip it or something...
		if ($attachmentOptions['size'] + $dirSize > $modSettings['attachmentDirSizeLimit'] * 1024)
			$attachmentOptions['errors'][] = 'directory_full';
		// Soon to be too big - warn the admins...
		elseif (!isset($modSettings['attachment_full_notified']) && $modSettings['attachmentDirSizeLimit'] > 4000 && $attachmentOptions['size'] + $dirSize > ($modSettings['attachmentDirSizeLimit'] - 2000) * 1024)
		{
			require_once($sourcedir . '/Subs-Admin.php');
			emailAdmins('admin_attachments_full');
			updateSettings(array('attachment_full_notified' => 1));
		}
	}

	// Check if the file already exists.... (for those who do not encrypt their filenames...)
	if (empty($modSettings['attachmentEncryptFilenames']))
	{
		// Make sure they aren't trying to upload a nasty file.
		$disabledFiles = array('con', 'com1', 'com2', 'com3', 'com4', 'prn', 'aux', 'lpt1', '.htaccess', 'index.php');
		if (in_array(strtolower(basename($attachmentOptions['name'])), $disabledFiles))
			$attachmentOptions['errors'][] = 'bad_filename';

		// Check if there's another file with that name...
		$request = $smcFunc['db_query']('', '
			SELECT id_attach
			FROM {db_prefix}attachments
			WHERE filename = {string:filename}
			LIMIT 1',
			array(
				'filename' => strtolower($attachmentOptions['name']),
			)
		);
		if ($smcFunc['db_num_rows']($request) > 0)
			$attachmentOptions['errors'][] = 'taken_filename';
		$smcFunc['db_free_result']($request);
	}

	if (!empty($attachmentOptions['errors']))
		return false;

	if (!is_writable($attach_dir))
		fatal_lang_error('attachments_no_write', 'critical');

	// Assuming no-one set the extension let's take a look at it.
	if (empty($attachmentOptions['fileext']))
	{
		$attachmentOptions['fileext'] = strtolower(strrpos($attachmentOptions['name'], '.') !== false ? substr($attachmentOptions['name'], strrpos($attachmentOptions['name'], '.') + 1) : '');
		if (strlen($attachmentOptions['fileext']) > 8 || '.' . $attachmentOptions['fileext'] == $attachmentOptions['name'])
			$attachmentOptions['fileext'] = '';
	}

	$smcFunc['db_insert']('',
		'{db_prefix}attachments',
		array(
			'id_folder' => 'int', 'id_msg' => 'int', 'filename' => 'string-255', 'file_hash' => 'string-40', 'fileext' => 'string-8',
			'size' => 'int', 'width' => 'int', 'height' => 'int',
			'mime_type' => 'string-20', 'approved' => 'int',
		),
		array(
			$id_folder, (int) $attachmentOptions['post'], $attachmentOptions['name'], $attachmentOptions['file_hash'], $attachmentOptions['fileext'],
			(int) $attachmentOptions['size'], (empty($attachmentOptions['width']) ? 0 : (int) $attachmentOptions['width']), (empty($attachmentOptions['height']) ? '0' : (int) $attachmentOptions['height']),
			(!empty($attachmentOptions['mime_type']) ? $attachmentOptions['mime_type'] : ''), (int) $attachmentOptions['approved'],
		),
		array('id_attach')
	);
	$attachmentOptions['id'] = $smcFunc['db_insert_id']('{db_prefix}attachments', 'id_attach');

	if (empty($attachmentOptions['id']))
		return false;

	$attachmentOptions['destination'] = getAttachmentFilename(basename($attachmentOptions['name']), $attachmentOptions['id'], $id_folder, false, $attachmentOptions['file_hash']);
	
	// Create the actual attachment file.
	if(!rename($attachmentOptions['tmp_name'],$attachmentOptions['destination']))
		fatal_lang_error('attach_timeout', 'critical');

	// Attempt to chmod it.
	@chmod($attachmentOptions['destination'], 0644);

	$size = @getimagesize($attachmentOptions['destination']);

	list ($attachmentOptions['width'], $attachmentOptions['height']) = empty($size) ? array(null, null, null) : $size;

	// Security checks for images
	// Do we have an image? If yes, we need to check it out!
	if (isset($validImageTypes[$size[2]]))
	{
		if (!checkImageContents($attachmentOptions['destination'], !empty($modSettings['attachment_image_paranoid'])))
		{
			// It's bad. Last chance, maybe we can re-encode it?
			if (empty($modSettings['attachment_image_reencode']) || (!reencodeImage($attachmentOptions['destination'], $size[2])))
			{
				// Nothing to do: not allowed or not successful re-encoding it.
				require_once($sourcedir . '/ManageAttachments.php');
				removeAttachments(array(
					'id_attach' => $attachmentOptions['id']
				));
				$attachmentOptions['id'] = null;
				$attachmentOptions['errors'][] = 'bad_attachment';

				return false;
			}
			// Success! However, successes usually come for a price:
			// we might get a new format for our image...
			$old_format = $size[2];
			$size = @getimagesize($attachmentOptions['destination']);
			if (!(empty($size)) && ($size[2] != $old_format))
			{
				// Let's update the image information
				// !!! This is becoming a mess: we keep coming back and update the database,
				//  instead of getting it right the first time.
				if (isset($validImageTypes[$size[2]]))
				{
					$attachmentOptions['mime_type'] = 'image/' . $validImageTypes[$size[2]];
					$smcFunc['db_query']('', '
						UPDATE {db_prefix}attachments
						SET
							mime_type = {string:mime_type}
						WHERE id_attach = {int:id_attach}',
						array(
							'id_attach' => $attachmentOptions['id'],
							'mime_type' => $attachmentOptions['mime_type'],
						)
					);
				}
			}
		}
	}

	if (!empty($attachmentOptions['skip_thumbnail']) || (empty($attachmentOptions['width']) && empty($attachmentOptions['height'])))
		return true;

	// Like thumbnails, do we?
	if (!empty($modSettings['attachmentThumbnails']) && !empty($modSettings['attachmentThumbWidth']) && !empty($modSettings['attachmentThumbHeight']) && ($attachmentOptions['width'] > $modSettings['attachmentThumbWidth'] || $attachmentOptions['height'] > $modSettings['attachmentThumbHeight']))
	{
		if (createThumbnail($attachmentOptions['destination'], $modSettings['attachmentThumbWidth'], $modSettings['attachmentThumbHeight']))
		{
			// Figure out how big we actually made it.
			$size = @getimagesize($attachmentOptions['destination'] . '_thumb');
			list ($thumb_width, $thumb_height) = $size;

			if (!empty($size['mime']))
				$thumb_mime = $size['mime'];
			elseif (isset($validImageTypes[$size[2]]))
				$thumb_mime = 'image/' . $validImageTypes[$size[2]];
			// Lord only knows how this happened...
			else
				$thumb_mime = '';

			$thumb_filename = $attachmentOptions['name'] . '_thumb';
			$thumb_size = filesize($attachmentOptions['destination'] . '_thumb');
			$thumb_file_hash = getAttachmentFilename($thumb_filename, false, null, true);

			// To the database we go!
			$smcFunc['db_insert']('',
				'{db_prefix}attachments',
				array(
					'id_folder' => 'int', 'id_msg' => 'int', 'attachment_type' => 'int', 'filename' => 'string-255', 'file_hash' => 'string-40', 'fileext' => 'string-8',
					'size' => 'int', 'width' => 'int', 'height' => 'int', 'mime_type' => 'string-20', 'approved' => 'int',
				),
				array(
					$id_folder, (int) $attachmentOptions['post'], 3, $thumb_filename, $thumb_file_hash, $attachmentOptions['fileext'],
					$thumb_size, $thumb_width, $thumb_height, $thumb_mime, (int) $attachmentOptions['approved'],
				),
				array('id_attach')
			);
			$attachmentOptions['thumb'] = $smcFunc['db_insert_id']('{db_prefix}attachments', 'id_attach');

			if (!empty($attachmentOptions['thumb']) && $attachmentOptions['imagetype'] != 4)
			{
				$smcFunc['db_query']('', '
					UPDATE {db_prefix}attachments
					SET id_thumb = {int:id_thumb}
					WHERE id_attach = {int:id_attach}',
					array(
						'id_thumb' => $attachmentOptions['thumb'],
						'id_attach' => $attachmentOptions['id'],
					)
				);

				rename($attachmentOptions['destination'] . '_thumb', getAttachmentFilename($thumb_filename, $attachmentOptions['thumb'], $id_folder, false, $thumb_file_hash));
			}
			// If this is a link, we only want the thumbnail. Delete the original.
			elseif (!empty($attachmentOptions['thumb']) && $attachmentOptions['imagetype'] == 4)
			{
				$smcFunc['db_query']('', '
					DELETE FROM {db_prefix}attachments
					WHERE id_attach = {int:id_attach}',
					array(
						'id_attach' => $attachmentOptions['id'],
					)
				);

				rename($attachmentOptions['destination'] . '_thumb', getAttachmentFilename($thumb_filename, $attachmentOptions['thumb'], $id_folder, false, $thumb_file_hash));
				unlink($attachmentOptions['destination']);
			}			
		}
	}	

	return true;
}


?>